import { Component, STATE, ATTRIBUTE } from '../../utils/framework.js'
import { enableGesture } from '../../utils/gesture.js'
import { Timeline, Animation } from "../../utils/animation.js";
import { ease } from '../../utils/ease.js'

export { STATE, ATTRIBUTE } from '../../utils/framework.js' // 其他文件可能也会访问

export class Carousel extends Component {
  constructor() {
    super();
  }

  render() {
    // console.log(this.attributes.src)
    this.root = document.createElement('div');
    this.root.classList.add('carousel');

    for(let record of this[ATTRIBUTE].src) {
      let child = document.createElement('div');
      child.style.backgroundImage = `url(${record.img})`
      this.root.appendChild(child);
    }

    enableGesture(this.root); // 添加手势
    let timeline = new Timeline(); // 添加时间线 ，播放动画
    timeline.start();

    let handler = null; // 存储动画方便操作
    let children = this.root.children;

    // let position = 0; // 当前滚动到的位置
    this[STATE].position = 0;

    let t = 0;
    let ax = 0;
    let TDuration = 500; // 动画总时长 

    this.root.addEventListener('start', event => {
      // 开始时先暂停一下避免出现干扰
      timeline.pause();
      clearInterval(handler);
      // 当 start 被触发，计算 ax 的时候需要校正 ax
      if (Date.now() - t < TDuration) {
        // 计算动画的progress 动画时间的进度 = (当前时间 - 动画开始时间) / 动画总时长
        let progress = (Date.now() - t) / TDuration
        // 动画的偏移量 = 动画时间的进度 * 500  500：图片宽度
        ax = ease(progress) * 500 - 500 // 因为移动到下一帧 要减去500
      } else {
        // 如果图片在 TDuration 时间内已经滚出画面，但 nextPicture 还没被触发，progress 会大于 1
        // ax 也会指向还没播放的位置，所以这里 ax 要清零
        ax = 0;
      }
    })

    this.root.addEventListener('tap', event => { // 点击图片时
      this.triggerEvent('click', {
        position: this[STATE].position,
        data: this[ATTRIBUTE].src[this[STATE].position]
      })
    })

    this.root.addEventListener('pan', event => { // 监听手势事件
      // console.log(event.clientX - event.startX);
      // 计算拖拽的偏移量(还需要减去动画时的偏移量)
      let x = event.clientX - event.startX - ax;
      let current = this[STATE].position - ((x - x % 500) / 500);

      for (let offset of [-1, 0, 1]) {
        let pos = current + offset;
        pos = (pos % children.length + children.length) % children.length;

        children[pos].style.transition = 'none';
        children[pos].style.transform = `translateX(${- pos * 500 + offset * 500 + x % 500}px)`;
      }
    })

    this.root.addEventListener('end', event => {

      timeline.reset();
      timeline.start();
      handler = setInterval(nextPicture, 3000);

      let x = event.clientX - event.startX - ax;
      let current = this[STATE].position - ((x - x % 500) / 500);

      let direction = Math.round((x % 500) / 500); // -1, 0, 1

      if (event.isFlick) {
        if (event.velocity < 0) {
          direction = Math.ceil((x % 500) / 500)
        } else {
          direction = Math.floor((x % 500) / 500)
        }
        console.log(event.velocity);
      }

      for (let offset of [-1, 0, 1]) {
        let pos = current + offset;
        pos = (pos % children.length + children.length) % children.length;

        children[pos].style.transition = 'none';
        timeline.add(new Animation(
          children[pos].style, "transform", 
          - pos * 500 + offset * 500 + x % 500,
          - pos * 500 + offset * 500 + direction * 500,
          TDuration, 0, ease, v => `translateX(${v}px)`
        ));
      }
      // 重新计算 position direction代表方向
      this[STATE].position = this[STATE].position - ((x - x % 500) / 500) - direction;
      // 如果拖动的比较远，x值可能会负 需要变为正数
      this[STATE].position = (this[STATE].position % children.length + children.length) % children.length;
    
      this.triggerEvent('change', { position: this[STATE].position })
    })

    let nextPicture = () => { // 添加动画
      let children = this.root.children;
      let nextPosition = (this[STATE].position + 1) % children.length;

      let current = children[this[STATE].position];
      let next = children[nextPosition];

      t = Date.now(); // 保存动画开始的时间

      // 触发animation
      timeline.add(new Animation(current.style, "transform", 
        - this[STATE].position * 500, -500 - this[STATE].position * 500, TDuration, 0, ease,
        v => `translateX(${v}px)`
      ));
      timeline.add(new Animation(next.style, "transform", 
        500 - nextPosition * 500, - nextPosition * 500, TDuration, 0, ease,
        v => `translateX(${v}px)`
      ));

      this[STATE].position = nextPosition;
      this.triggerEvent('change', { position: this[STATE].position })
    }

    handler = setInterval(nextPicture, 3000);

    // 拖动滑动
    /* let position = 0;
    this.root.addEventListener("mousedown", event => {
      let children = this.root.children;
      let startX = event.clientX; //, startY = event.clientY;

      let move = event => {
        let x = event.clientX - startX; //, y = event.clientY - startY;

        let current = position - ((x - x % 500) / 500);
        for (let offset of [-2, -1, 0, 1, 2]) {
          let pos = current + offset;
          pos = (pos + children.length) % children.length;

          children[pos].style.transition = 'none';
          children[pos].style.transform = `translateX(${- pos * 500 + offset * 500 + x % 500}px)`;
        }
      }

      let up = event => {
        let x = event.clientX - startX;
        position = position - Math.round(x / 500);

        for (let offset of [0, - Math.sign(Math.round(x / 500) - x + 250 * Math.sign(x))]) {
          let pos = position + offset;
          pos = (pos + children.length) % children.length;

          children[pos].style.transition = '';
          children[pos].style.transform = `translateX(${- pos * 500 + offset * 500}px)`;
        }

        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);
      }

      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    }) */

    // 图片轮播
    /* let currentIndex = 0;
    setInterval(() => {
      let children = this.root.children;
      let nextIndex = (currentIndex + 1) % children.length;

      let current = children[currentIndex];
      let next = children[nextIndex];
      next.style.transition = 'none';
      next.style.transform = `translateX(${100 - nextIndex * 100}%)`

      setTimeout(() => {
        next.style.transition = '';
        current.style.transform = `translateX(${-100 - currentIndex * 100}%)`;
        next.style.transform = `translateX(${- nextIndex * 100}%)`;

        currentIndex = nextIndex;
      }, 16);

    }, 3000);*/

    return this.root;
  }
}